#ifndef FABRICACOMPONENTES_H_
#define FABRICACOMPONENTES_H_

#include <map>
#include <string>
#include <memory>
#include "RegistroDisco.h"
#include "RegistroMemoria.h"
#include "BloqueDisco.h"
#include "BloqueMemoria.h"
#include "Singleton.h"

namespace Toolkit
{

class FabricaComponentes: public Singleton<FabricaComponentes> //Alto PatéRn de Foie
{
public:

    Componente* nuevaInstancia(const string &keyword)
    {
        return FabricaComponentes::instancias[keyword]->nuevaInstancia();
    }

    Componente* nuevaInstancia(const char &caracter)
    {
        return FabricaComponentes::instancias[FabricaComponentes::caracteres[caracter]]->nuevaInstancia();
    }

    void configurar(const TipoSerializacion &tSerializacion,
            const unsigned long int &tamanoBloque)
    {
        if (instancias.size() == 0)
        {
            caracteres['r'] = "RegistroMemoria";
            caracteres['R'] = "RegistroDisco";
            caracteres['b'] = "BloqueMemoria";
            caracteres['B'] = "BloqueDisco";
        }
        else
        {
            cleanup();
        }

        instancias["RegistroMemoria"] = new RegistroMemoria(tSerializacion);
        instancias["RegistroDisco"] = new RegistroDisco(tSerializacion);
        instancias["BloqueDisco"] = new BloqueDisco(tamanoBloque,
                tSerializacion);
        instancias["BloqueMemoria"] = new BloqueMemoria(tamanoBloque,
                tSerializacion);
    }

    void cleanup()
    {
        for (map<string, Componente*>::iterator it = instancias.begin(); it
                != instancias.end(); it++)
        {
            delete (*it).second;
        }
    }

private:
    map<string, Componente*> instancias;
    map<char, string> caracteres;

};

}

#endif /* FABRICACOMPONENTES_H_ */
